#ifndef PROGRAMMANAGER
#define PROGRAMMANAGER

#include <string>
#include <map>
#include <vector>

class CallingContext;
class CallingInstance;

class IdentificatorTable;

/**
    @brief gestion de l'exécution d'un programme

    Classe statique qui gère l'exécution d'un programme
    @todo méthode de réinitialisation
    @todo méthode d'initialisation à partir d'un fichier
*/
class ProgramManager
{
	public:
        /**
            @brief création du contexte d'une fonction

            Cette fonction va créer le contexte générique associé à une fonction (au moment de l'analyse).
            modifie la valeur de l'attribut _currentContext pour qu'elle pointe sur le nouveau contexte
            @param [in] index l'indice du nom de la fonction dans la table des identificateurs
        */
		static void createCallingContext ( unsigned int index );
		/**
            @brief contexte courant

            accède au contexte courant (en cours d'analyse)
            @return le contexte courant
		*/
		static CallingContext* getCurrentContext ();
		/**
            @brief accès à un contexte

            accède au contexte associé à une fonction.
            Cette méthode est à utiliser au moment des appels de fonctions et procédures
            @param [in] index l'indice associé à l'identificateur de la fonction
            @return le contexte associé à cette fonction
        */
		static CallingContext* getCallingContext ( unsigned int index );
		/**
            @brief accès à l'appel de fonction en cours d'exécution

            renvoie l'instance de contexte de la fonction en cours d'exécution
            @return l'instance de contexte
        */
		static CallingInstance* getCurrentInstance ();
		/**
            @brief gestion des identificateurs

            Ajoute un identificateur à la liste des identificateurs du programme.
            Si l'identificateur est déjà présent, cette fonctionne ne modifie rien
            @param [in] name la chaine de caractère associée à l'identificateur
            @return l'indice de l'identificateur dans la table
        */
		static unsigned int addIdentificator ( const std::string& name );
		/**
            @brief gestion des noms des identificateurs

            accède au nom d'un identificateur de la table
            @param [in] index l'indice de l'identificateur dans la table
            @return le nom associée à l'identificateur
        */
		static const std::string& getNameOf ( const unsigned int index );
		/**
            @brief gestion des identificateurs

            accède à l'indice d'un identificateur dans la table
            @param [in] name la chaine de caractère associée à l'identificateur
            @return l'indice de l'identificateur dans la table
        */
		static const unsigned int getIndexOf ( const std::string& name );
		/**
            @brief parcours des contextes d'exécution

            gestion de l'itérateur permettant le parcours des contextes d'exécution
            @return un itérateur sur le début de la liste des contextes d'exécution
		*/
		static std::map < unsigned int, CallingContext* >::const_iterator begin ();
		/**
            @brief parcours des contextes d'exécution

            gestion de l'itérateur permettant le parcours des contextes d'exécution
            @return un itérateur sur la fin de la liste des contextes d'exécution
		*/
		static std::map < unsigned int, CallingContext* >::const_iterator end ();
		friend class CallingContext;
		friend class CallingInstance;
	private:
        /// les contextes génériques associés aux fonctions
		static std::map < unsigned int, CallingContext* > _allContext;
		/// la table des identificateurs du programme
		static IdentificatorTable* _identificators;
		/// le contexte générique en cours de création
		static CallingContext* _currentContext;
		/// la pile des appels de fonctions
        static std::vector < CallingInstance* > _executionStack;
};

#endif
